const express = require('express');
const multer = require('multer');
const path = require('path');
const cors = require('cors');
const fs = require('fs');
const jwt = require('jsonwebtoken');

// 创建两个 Express 应用实例
const app = express();  // API 服务器
const fileServer = express();  // 文件服务器

// 确保必要的文件夹存在
function ensureDirectoriesExist() {
    const directories = ['upload', 'temp'];
    directories.forEach(dir => {
        if (!fs.existsSync(dir)) {
            fs.mkdirSync(dir);
            console.log(`创建文件夹: ${dir}`);
        }
    });
}

// 清理临时文件
function cleanupTempFiles() {
    const tempDir = 'temp';
    if (fs.existsSync(tempDir)) {
        fs.readdirSync(tempDir).forEach(file => {
            const filePath = path.join(tempDir, file);
            try {
                fs.unlinkSync(filePath);
                console.log(`清理临时文件: ${file}`);
            } catch (err) {
                console.error(`清理临时文件失败: ${file}`, err);
            }
        });
    }
}

// 添加在文件顶部的常量声明部分
const SOFTWARE_DB_FILE = 'software_db.json';
const USERS_DB_FILE = 'users_db.json';

// 添加 JWT 密钥
const JWT_SECRET = 'your-secret-key';  // 在实际应用中应该使用环境变量

// 添加数据存储相关函数
function loadSoftwareList() {
    try {
        if (fs.existsSync(SOFTWARE_DB_FILE)) {
            const data = fs.readFileSync(SOFTWARE_DB_FILE, 'utf8');
            return JSON.parse(data);
        }
    } catch (error) {
        console.error('读取软件列表失败:', error);
    }
    return [];
}

function saveSoftwareList(list) {
    try {
        fs.writeFileSync(SOFTWARE_DB_FILE, JSON.stringify(list, null, 2));
    } catch (error) {
        console.error('保存软件列表失败:', error);
    }
}

// 初始化软件列表
let softwareList = loadSoftwareList();

// 加载用户列表
function loadUserList() {
    try {
        if (fs.existsSync(USERS_DB_FILE)) {
            const data = fs.readFileSync(USERS_DB_FILE, 'utf8');
            return JSON.parse(data);
        }
    } catch (error) {
        console.error('读取用户列表失败:', error);
    }
    return [];
}

// 保存用户列表
function saveUserList(list) {
    try {
        console.log('保存用户列表:', list);  // 添加调试日志
        fs.writeFileSync(USERS_DB_FILE, JSON.stringify(list, null, 2));
        console.log('用户列表保存成功');  // 添加调试日志
    } catch (error) {
        console.error('保存用户列表失败:', error);
        throw error;  // 抛出错误以便上层处理
    }
}

// 初始化用户列表
let userList = loadUserList();

// 启用 CORS
app.use(cors());

// 设置 multer 存储配置
const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, 'temp'); // 所有文件先存储到临时文件夹
    },
    filename: function (req, file, cb) {
        // 使用原始文件名作为临时文件名
        const chunkIndex = req.headers['x-chunk-index'];
        const identifier = req.headers['x-identifier'];
        cb(null, `${identifier}-${chunkIndex}`);
    }
});

const upload = multer({ storage: storage });

// 添加版本号验证函数
function validateVersion(version) {
    const versionPattern = /^v?\d+\.\d+(\.\d+)?(-[a-zA-Z0-9]+)?$/;
    return versionPattern.test(version);
}

// 修改 Base64 解码函数
function decodeHeaderValue(str) {
    try {
        // 首先检查是否是有效的 Base64 字符串
        if (!str || typeof str !== 'string') {
            console.error('无效的输入字符串:', str);
            return '';
        }

        // 添加错误处理的 Base64 解码
        let decoded;
        try {
            decoded = Buffer.from(str, 'base64').toString();
        } catch (error) {
            console.error('Base64 解码失败:', error);
            return str;
        }

        // 添加错误处理的 URI 解码
        try {
            return decodeURIComponent(decoded);
        } catch (error) {
            console.error('URI 解码失败:', error);
            return decoded;
        }
    } catch (error) {
        console.error('解码过程出错:', error);
        return str;
    }
}

// API 路由前缀
app.use('/api', express.json());

// 修改上传路由，添加 multer 中间件
app.post('/api/uploadChunk', authenticateToken, upload.single('chunk'), async (req, res) => {
    try {
        console.log('收到分块上传请求');  // 添加调试日志
        
        if (!req.file) {
            console.error('没有接收到文件块');  // 添加调试日志
            return res.status(400).json({ message: '没有接收到文件块' });
        }

        const chunkIndex = parseInt(req.headers['x-chunk-index']);
        const totalChunks = parseInt(req.headers['x-total-chunks']);
        const identifier = req.headers['x-identifier'];

        console.log('分块信息:', {  // 添加调试日志
            chunkIndex,
            totalChunks,
            identifier,
            fileSize: req.file.size
        });

        // 添加错误处理的码过程
        let originalFilename, version, softwareName, description, exeName;
        try {
            originalFilename = decodeHeaderValue(req.headers['x-filename']);
            version = decodeHeaderValue(req.headers['x-version']);
            softwareName = decodeHeaderValue(req.headers['x-software-name']);
            description = decodeHeaderValue(req.headers['x-description']);
            exeName = decodeHeaderValue(req.headers['x-exe-name']);
            
            console.log('解码后的信息:', {  // 添加调试日志
                originalFilename,
                version,
                softwareName,
                description,
                exeName
            });
        } catch (error) {
            console.error('头部解码失败:', error);
            return res.status(400).json({ message: '请求头解析失败' });
        }

        // 验证前分块
        const stats = fs.statSync(req.file.path);
        if (stats.size === 0) {
            fs.unlinkSync(req.file.path);
            throw new Error('接收到的分块大小为0');
        }

        if (chunkIndex === totalChunks - 1) {
            if (!validateVersion(version)) {
                return res.status(400).json({ message: '版本号格式不正确' });
            }

            try {
                const finalFilename = await mergeChunks(identifier, totalChunks, originalFilename);
                
                // 检查是否是更新现有软件
                const updateSoftwareId = req.headers['x-update-software-id'];
                if (updateSoftwareId) {
                    const id = parseInt(updateSoftwareId);
                    const software = softwareList.find(s => s.id === id);
                    if (software) {
                        // 删除旧文件
                        const oldFilePath = path.join('upload', software.filename);
                        if (fs.existsSync(oldFilePath)) {
                            fs.unlinkSync(oldFilePath);
                        }
                        
                        // 更新软件信息
                        software.name = softwareName;
                        software.version = version;
                        software.description = description;
                        software.filename = finalFilename;
                        software.exeName = exeName || '';
                        software.updateTime = new Date().toISOString();
                        
                        saveSoftwareList(softwareList);
                        
                        return res.json({
                            message: '软件更新成功',
                            software: software
                        });
                    }
                }

                // 如果不是更新，添加新软件
                const softwareInfo = {
                    id: Date.now(),
                    name: softwareName,
                    version: version,
                    description: description,
                    filename: finalFilename,
                    exeName: exeName || '',
                    uploadTime: new Date().toISOString(),
                    authorizedUsers: []
                };
                softwareList.push(softwareInfo);
                saveSoftwareList(softwareList);

                res.json({ 
                    message: '文件上传成功',
                    filename: finalFilename,
                    software: softwareInfo
                });
            } catch (error) {
                console.error('合并文件失败:', error);
                res.status(500).json({ message: '合并文件失败: ' + error.message });
            }
        } else {
            res.json({ message: '分块上传成功' });
        }
    } catch (error) {
        console.error('上传处理错误:', error);
        res.status(500).json({ message: '上传处理失败' });
    }
});

// 合并文件分块
async function mergeChunks(identifier, totalChunks, originalFilename) {
    const chunkDir = 'temp';
    const uploadDir = 'upload';
    
    // 获取不带扩展名的文件名和扩展名
    const ext = path.extname(originalFilename);
    const baseFilename = path.basename(originalFilename, ext);
    
    // 检查是否存在同名文件，如果存在则添加序号
    let finalFilename = originalFilename;
    let counter = 1;
    while (fs.existsSync(path.join(uploadDir, finalFilename))) {
        finalFilename = `${baseFilename}(${counter})${ext}`;
        counter++;
    }

    const finalPath = path.join(uploadDir, finalFilename);
    const writeStream = fs.createWriteStream(finalPath);

    try {
        let totalSize = 0;
        // 验证并合并分块
        for (let i = 0; i < totalChunks; i++) {
            const chunkPath = path.join(chunkDir, `${identifier}-${i}`);
            if (!fs.existsSync(chunkPath)) {
                throw new Error(`缺少分块文件: ${i}`);
            }
            const chunkStats = fs.statSync(chunkPath);
            if (chunkStats.size === 0) {
                throw new Error(`分块 ${i} 大小为0`);
            }
            totalSize += chunkStats.size;
        }

        // 合并分块
        for (let i = 0; i < totalChunks; i++) {
            const chunkPath = path.join(chunkDir, `${identifier}-${i}`);
            await new Promise((resolve, reject) => {
                const readStream = fs.createReadStream(chunkPath);
                readStream.pipe(writeStream, { end: i === totalChunks - 1 });
                readStream.on('end', () => {
                    fs.unlink(chunkPath, (err) => {
                        if (err) console.error('删除分块文件失败:', err);
                        resolve();
                    });
                });
                readStream.on('error', reject);
            });
        }

        // 验证最终文件
        const finalStats = fs.statSync(finalPath);
        if (finalStats.size === 0 || finalStats.size !== totalSize) {
            fs.unlinkSync(finalPath);
            throw new Error('文件合并后大小不正确');
        }

        console.log('文件合并完成:', finalFilename, '大小:', finalStats.size);
        return finalFilename;
    } catch (error) {
        if (fs.existsSync(finalPath)) {
            fs.unlinkSync(finalPath);
        }
        throw error;
    }
}

// 添加获取软件列表的路由
app.get('/software-list', authenticateToken, (req, res) => {
    console.log('获取软件列表请求');  // ���加调试日志
    console.log('当前软件列表:', softwareList);  // 添加调试日志
    res.json(softwareList || []);  // 确保返回数组
});

// 添加删除软件的路由
app.delete('/software/:id', (req, res) => {
    const id = parseInt(req.params.id);
    const software = softwareList.find(s => s.id === id);
    
    if (software) {
        // 删除文件
        const filePath = path.join('upload', software.filename);
        if (fs.existsSync(filePath)) {
            fs.unlinkSync(filePath);
        }
        
        // 从列表中移除
        softwareList = softwareList.filter(s => s.id !== id);
        saveSoftwareList(softwareList);
        
        res.json({ message: '软件删除成功' });
    } else {
        res.status(404).json({ message: '软件不存在' });
    }
});

// 添加编辑软件信息的路由
app.put('/software/:id', express.json(), (req, res) => {
    const id = parseInt(req.params.id);
    const software = softwareList.find(s => s.id === id);
    const { name, version, description, exeName } = req.body;
    
    if (!software) {
        return res.status(404).json({ message: '软件不存在' });
    }

    if (!validateVersion(version)) {
        return res.status(400).json({ message: '版本号格式不正确' });
    }

    // 更新软件信息
    software.name = name;
    software.version = version;
    software.description = description;
    software.exeName = exeName || '';
    software.updateTime = new Date().toISOString();
    
    // 保存更新
    saveSoftwareList(softwareList);
    
    res.json({ 
        message: '软件信息更新成功',
        software: software 
    });
});

// 获取用户列表
app.get('/users', (req, res) => {
    console.log('获取用户列表请求');  // 添加调试日志
    console.log('当前用户列表:', userList);  // 添加调试日志
    res.json(userList || []);
});

// 添加用户
app.post('/users', express.json(), (req, res) => {
    const { username, password, role } = req.body;

    if (!username || !password) {
        return res.status(400).json({ message: '用户名和密码不能为空' });
    }

    // 检查用户名是否已存在
    if (userList.some(u => u.username === username)) {
        return res.status(400).json({ message: '用户名已存在' });
    }

    const user = {
        id: Date.now(),
        username,
        password, // 实际应用中应该加密存储
        role: role || 'user',
        createTime: new Date().toISOString()
    };

    userList.push(user);
    saveUserList(userList);

    // 返回用户信息时删除密码字段
    const { password: _, ...userWithoutPassword } = user;
    res.json({ 
        message: '用户添加成功',
        user: userWithoutPassword
    });
});

// 删除用户
app.delete('/users/:id', (req, res) => {
    const id = parseInt(req.params.id);
    console.log('删除用户请求:', id);  // 添加调试日志
    console.log('当前用户列表:', userList);  // 添加调试日志
    
    const userIndex = userList.findIndex(u => u.id === id);
    
    if (userIndex === -1) {
        console.log('用户不存在:', id);  // 添加调试日志
        return res.status(404).json({ message: '用户不存在' });
    }

    try {
        // 从列表中移除
        userList.splice(userIndex, 1);
        saveUserList(userList);
        
        console.log('用户删除成功:', id);  // 添加调试日志
        console.log('更新后的用户列表:', userList);  // 添加调试日志
        res.json({ message: '用户删除成功' });
    } catch (error) {
        console.error('删除用户失败:', error);  // 添加错误日志
        res.status(500).json({ message: '删除用户失败' });
    }
});

// 编辑用户
app.put('/users/:id', express.json(), (req, res) => {
    const id = parseInt(req.params.id);
    const { username, role } = req.body;
    const userIndex = userList.findIndex(u => u.id === id);
    
    if (userIndex === -1) {
        return res.status(404).json({ message: '用户不存在' });
    }

    // 检查用户名是否已被其他用户使用
    if (userList.some(u => u.id !== id && u.username === username)) {
        return res.status(400).json({ message: '用户名已存在' });
    }

    // 更新用户信息
    userList[userIndex] = {
        ...userList[userIndex],
        username,
        role,
        updateTime: new Date().toISOString()
    };

    saveUserList(userList);

    // 返回用户信息时删除密码字段
    const { password: _, ...userWithoutPassword } = userList[userIndex];
    res.json({ 
        message: '用户信息更新成功',
        user: userWithoutPassword
    });
});

// 添加软件授权路由
app.put('/software/:id/authorize', express.json(), (req, res) => {
    const id = parseInt(req.params.id);
    const { userIds } = req.body;
    const software = softwareList.find(s => s.id === id);
    
    if (!software) {
        return res.status(404).json({ message: '软件不存在' });
    }

    // 验证用户ID是否有效
    const validUserIds = userIds.filter(userId => 
        userList.some(u => u.id === userId)
    );

    software.authorizedUsers = validUserIds;
    saveSoftwareList(softwareList);
    
    res.json({ 
        message: '授权更新成功',
        software: software 
    });
});

// 添加登录路由
app.post('/login', express.json(), (req, res) => {
    const { username, password } = req.body;

    // 查找用户
    const user = userList.find(u => u.username === username && u.password === password);
    
    if (!user) {
        return res.status(401).json({ message: '用户名或密码错误' });
    }

    // 只允许管理员登录
    if (user.role !== 'admin') {
        return res.status(403).json({ message: '只有管理员可以登录系统' });
    }

    // 生成 JWT token
    const token = jwt.sign(
        { userId: user.id, username: user.username, role: user.role },
        JWT_SECRET,
        { expiresIn: '24h' }
    );

    // 返回用户信息和token（不包含密码）
    const { password: _, ...userWithoutPassword } = user;
    res.json({
        message: '登录成功',
        user: userWithoutPassword,
        token
    });
});

// 添加验证中间件
function authenticateToken(req, res, next) {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];

    if (!token) {
        return res.status(401).json({ message: '未提供认证token' });
    }

    jwt.verify(token, JWT_SECRET, (err, user) => {
        if (err) {
            return res.status(403).json({ message: '��效的token' });
        }
        req.user = user;
        next();
    });
}

// 配置文件服务器
fileServer.use('/', express.static(__dirname, {
    dotfiles: 'ignore',
    etag: false,
    extensions: ['htm', 'html'],
    index: false,  // 禁用目录默认页
    maxAge: '1d',
    redirect: false,
    setHeaders: function (res, path, stat) {
        res.set('x-timestamp', Date.now());
    }
}));

// 添加目录浏览功能
fileServer.get('*', function(req, res) {
    const dirPath = path.join(__dirname, req.path);
    
    // 检查路径是否存在
    if (!fs.existsSync(dirPath)) {
        return res.status(404).send('Not found');
    }

    // 如果是文件，直接发送
    if (!fs.statSync(dirPath).isDirectory()) {
        return res.sendFile(dirPath);
    }

    // 读取目录内容
    fs.readdir(dirPath, (err, files) => {
        if (err) {
            console.error('读取目录失败:', err);
            return res.status(500).send('Error reading directory');
        }
        
        const fileList = files.map(file => {
            const filePath = path.join(dirPath, file);
            const stat = fs.statSync(filePath);
            return {
                name: file,
                isDirectory: stat.isDirectory(),
                size: stat.size,
                mtime: stat.mtime
            };
        });

        // 生成 HTML 页面
        const html = `
            <!DOCTYPE html>
            <html>
            <head>
                <title>Directory listing for ${req.path}</title>
                <style>
                    body { font-family: Arial, sans-serif; margin: 20px; }
                    .file-list { list-style: none; padding: 0; }
                    .file-list li { padding: 8px; border-bottom: 1px solid #eee; }
                    .file-list a { text-decoration: none; color: #333; }
                    .file-list .directory { font-weight: bold; color: #0066cc; }
                    .file-info { color: #666; font-size: 0.9em; margin-top: 4px; }
                    .path-info { margin-bottom: 20px; padding: 10px; background: #f5f5f5; }
                    .size { color: #888; }
                </style>
            </head>
            <body>
                <div class="path-info">
                    当前路径: ${req.path || '/'}
                </div>
                <ul class="file-list">
                    ${req.path !== '/' ? '<li><a href="..">..</a></li>' : ''}
                    ${fileList.map(file => `
                        <li>
                            <a href="${path.join(req.path, file.name)}" class="${file.isDirectory ? 'directory' : ''}">
                                ${file.name}${file.isDirectory ? '/' : ''}
                            </a>
                            <div class="file-info">
                                ${file.isDirectory ? 'Directory' : `${(file.size / 1024).toFixed(2)} KB`}
                                - Last modified: ${file.mtime.toLocaleString()}
                            </div>
                        </li>
                    `).join('')}
                </ul>
            </body>
            </html>
        `;
        
        res.send(html);
    });
});

// 启动 API 服务器
app.listen(3000, () => {
    console.log('API 服务器已启动，监听端口 3000');
    ensureDirectoriesExist();
});

// 启动文件服务器
fileServer.listen(3001, () => {
    console.log('文件服务器已启动，监听端口 3001');
    console.log('可以通过 http://localhost:3001 访问文件服务器');
}); 